﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Text;
using InkFx.WinControl.Core;
using InkFx.WinControl.Design;
using InkFx.WinControl.Utils;

namespace InkFx.WinControl.Theme
{
    /// <summary>
    /// 
    /// </summary>
    public struct SkinColor : ICloneable, IConvertible
    {
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="normalColor">Type: Color</param>
        public SkinColor(Color normalColor)
        {
            this.m_NormalColor = normalColor;
            this.m_HoverColor = ColorHelper.Light(normalColor);
            this.m_PressColor = ColorHelper.Dark(normalColor);
            this.m_FocusColor = this.m_HoverColor;
            this.m_DisableColor = ColorHelper.LightLight(normalColor);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="normalColor">Type: Color</param>
        /// <param name="hoverColor">Type: Color</param>
        public SkinColor(Color normalColor, Color hoverColor)
        {
            this.m_NormalColor = normalColor;
            this.m_HoverColor = hoverColor;
            this.m_PressColor = ColorHelper.Dark(normalColor);
            this.m_FocusColor = this.m_HoverColor;
            this.m_DisableColor = ColorHelper.LightLight(normalColor);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="normalColor">Type: Color</param>
        /// <param name="hoverColor">Type: Color</param>
        /// <param name="pressColor">Type: Color</param>
        public SkinColor(Color normalColor, Color hoverColor, Color pressColor)
        {
            this.m_NormalColor = normalColor;
            this.m_HoverColor = hoverColor;
            this.m_PressColor = pressColor;
            this.m_FocusColor = m_HoverColor;
            this.m_DisableColor = ColorHelper.LightLight(normalColor);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="normalColor">Type: Color</param>
        /// <param name="hoverColor">Type: Color</param>
        /// <param name="pressColor">Type: Color</param>
        /// <param name="focusColor">Type: Color</param>
        public SkinColor(Color normalColor, Color hoverColor, Color pressColor, Color focusColor)
        {
            this.m_NormalColor = normalColor;
            this.m_HoverColor = hoverColor;
            this.m_PressColor = pressColor;
            this.m_FocusColor = focusColor;
            this.m_DisableColor = ColorHelper.LightLight(normalColor);
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="normalColor">Type: Color</param>
        /// <param name="hoverColor">Type: Color</param>
        /// <param name="pressColor">Type: Color</param>
        /// <param name="focusColor">Type: Color</param>
        /// <param name="disableColor">Type: Color</param>
        public SkinColor(Color normalColor, Color hoverColor, Color pressColor, Color focusColor, Color disableColor)
        {
            this.m_NormalColor = normalColor;
            this.m_HoverColor = hoverColor;
            this.m_PressColor = pressColor;
            this.m_FocusColor = focusColor;
            this.m_DisableColor = disableColor;
        }

        /// <summary>
        /// 
        /// </summary>
        public static readonly SkinColor Empty = new SkinColor();  

        private Color m_NormalColor;
        private Color m_HoverColor;
        private Color m_PressColor;
        private Color m_FocusColor;
        private Color m_DisableColor;

        /// <summary>
        /// 
        /// </summary>
        public Color NormalColor
        {
            get { return this.m_NormalColor; }
            set { this.m_NormalColor = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public Color HoverColor
        {
            get { return this.m_HoverColor; }
            set { this.m_HoverColor = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public Color PressColor
        {
            get { return this.m_PressColor; }
            set { this.m_PressColor = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public Color FocusColor
        {
            get { return this.m_FocusColor; }
            set { this.m_FocusColor = value; }
        }
        /// <summary>
        /// 
        /// </summary>
        public Color DisableColor
        {
            get { return this.m_DisableColor; }
            set { this.m_DisableColor = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public bool IsEmpty
        {
            get { return m_NormalColor.A <= 0 && m_HoverColor.A <= 0 && m_PressColor.A <= 0 && m_FocusColor.A <= 0 && m_DisableColor.A <= 0; }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override string ToString()
        {
            return string.Format("{0}|{1}|{2}|{3}|{4}", ColorToString(m_NormalColor), ColorToString(m_HoverColor), ColorToString(m_PressColor), ColorToString(m_FocusColor), ColorToString(m_DisableColor));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color">Type: Color</param>
        /// <returns></returns>
        public static string ColorToString(Color color)
        {
            if (color.IsEmpty) return "Transparent";  
            TypeConverter converter = TypeDescriptor.GetConverter(typeof(Color));
            string str = (converter.ConvertTo(color, typeof(string)) ?? string.Empty).ToString();
            return string.Equals(str, "Empty", StringComparison.InvariantCultureIgnoreCase) ? "Transparent" : str;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="str">Type: string</param>
        /// <returns></returns>
        public static Color StringToColor(string str)
        {
            if (Tools.IsNullOrWhiteSpace(str) || string.Equals(str, "Empty", StringComparison.InvariantCultureIgnoreCase)) return Color.Transparent;
            TypeConverter converter = TypeDescriptor.GetConverter(typeof(Color));

            var obj = converter.ConvertFromString(str);
            Color color = (obj == null || Color.Empty.Equals(obj)) ? Color.Transparent : (Color)obj;
            return color;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="str">Type: string</param>
        /// <returns></returns>
        public static SkinColor From(string str)
        {
            if (Tools.IsNullOrWhiteSpace(str) || string.Equals(str, "Empty", StringComparison.InvariantCultureIgnoreCase)) return new SkinColor(Color.Transparent);


            string[] splits = str.Trim().Split(new[] { '|' });

            Color[] array = new Color[splits.Length];
            for (int i = 0; i < array.Length; ++i)
                array[i] = (Color)SkinColor.StringToColor(splits[i]);

            if (array.Length == 1)
                return new SkinColor(array[0]);
            if (array.Length == 2)
                return new SkinColor(array[0], array[1]);
            if (array.Length == 3)
                return new SkinColor(array[0], array[1], array[2]);
            if (array.Length == 4)
                return new SkinColor(array[0], array[1], array[2], array[3]);
            if (array.Length >= 5)
                return new SkinColor(array[0], array[1], array[2], array[3], array[4]);

            return new SkinColor(Color.Transparent);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="obj">Type: object</param>
        /// <returns></returns>
        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        /// <summary>
        /// 
        /// </summary>
        public static bool operator ==(SkinColor sc1, SkinColor sc2)
        {
            return (sc1.NormalColor == sc2.NormalColor && sc1.HoverColor == sc2.HoverColor && sc1.PressColor == sc2.PressColor && sc1.FocusColor == sc2.FocusColor && sc1.DisableColor == sc2.DisableColor);
        }
        /// <summary>
        /// 
        /// </summary>
        public static bool operator !=(SkinColor sc1, SkinColor sc2)
        {
            return !(sc1 == sc2);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="color">Type: SkinColor</param>
        /// <returns></returns>
        public static implicit operator Color(SkinColor color)
        {
            return color.NormalColor;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="color">Type: Color</param>
        /// <returns></returns>
        public static implicit operator SkinColor(Color color)
        {
            return new SkinColor(color);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public object Clone()
        {
            SkinColor clone = new SkinColor(NormalColor, HoverColor, PressColor, FocusColor, DisableColor);
            return clone;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <returns></returns>
        public Bitmap ToBitmap()
        {
            Bitmap bitmap = new Bitmap(32, 32);
            using (Graphics g = Graphics.FromImage(bitmap))
            {
                GUIHelper.FillBack(g, NormalColor, new Rectangle(0, 0, 32, 8), true);
                GUIHelper.FillBack(g, HoverColor, new Rectangle(0, 8, 32, 6), true);
                GUIHelper.FillBack(g, PressColor, new Rectangle(0, 14, 32, 6), true);
                GUIHelper.FillBack(g, FocusColor, new Rectangle(0, 20, 32, 6), true);
                GUIHelper.FillBack(g, DisableColor, new Rectangle(0, 26, 32, 6), true);
            }
            return bitmap;
        }



        TypeCode IConvertible.GetTypeCode()
        {
            return TypeCode.Object;
        }
        bool IConvertible.ToBoolean(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        char IConvertible.ToChar(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        sbyte IConvertible.ToSByte(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        byte IConvertible.ToByte(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        short IConvertible.ToInt16(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        ushort IConvertible.ToUInt16(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        int IConvertible.ToInt32(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        uint IConvertible.ToUInt32(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        long IConvertible.ToInt64(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        ulong IConvertible.ToUInt64(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        float IConvertible.ToSingle(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        double IConvertible.ToDouble(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        decimal IConvertible.ToDecimal(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        DateTime IConvertible.ToDateTime(IFormatProvider provider)
        {
            throw new NotImplementedException();
        }
        string IConvertible.ToString(IFormatProvider provider)
        {
            return this.ToString();
        }
        object IConvertible.ToType(Type conversionType, IFormatProvider provider)
        {
            if(conversionType==typeof(string)) return  this.ToString();
            return this.Clone();
        }
    }
}
